// require
var csv = require('csv');
var fs = require("fs");
var S = require("string");
var PATH = require('path');
var json2xml = require('json2xml');

// functions

function readJson(path)
{
  var buff = fs.readFileSync(path);
  var s = buff.toString();
  var j = JSON.parse(s);
  return j;
}

function deleteFolderRecursive(path)
{
  if( fs.existsSync(path) ) {
    fs.readdirSync(path).forEach(function(file,index){
        var curPath = path + "/" + file;
        if(fs.statSync(curPath).isDirectory())
        { // recurse
          deleteFolderRecursive(curPath);
        }
        else
        { // delete file
          fs.unlinkSync(curPath);
        }
    });
    fs.rmdirSync(path);
  }
}

function getHeaders(typeJson)
{
  var headers = [];
  
  for(h in typeJson)
  {
    headers.push(h);
  }
  
  return headers;
}

function fixValues(data, headers, typeJson)
{
  headers.forEach(function(h,i)
    {
      if(!data[h] && typeJson[h])
      {
        data[h] = 'N/A';
      }
      else if(data[h] && data[h]!=='N/A')
      {
        var tmp = data[h];
        tmp = S(tmp).capitalize().s;
        data[h] = tmp;
      }
      //else if(data[h] && data[h]==='N/A')
      //{
      //  if(h==='fashion1:Lavorazione' ||
      //     h==='fashion1:Grafica' ||
      //     h==='fashion1:Colore' ||
      //     h==='fashion1:TipologiaModello')
      //  {
      //    data[h] = '';
      //  }
      //}
    });
}

function addCsvHeaders(headers)
{
  var sourceFolderH = "sourceFolder";
  var cmNameH = "cm:name";
  var newHeaders = [sourceFolderH, cmNameH];
  newHeaders.push.apply(newHeaders, headers);
  
  return newHeaders;
}

function addEmptyRow(data, headers)
{
  var easyUserTitleHeaders = {};
  
  for(var i=0; i<headers.length; i++)
  {
    var titleI = "Title_" + i;
    var headerI = headers[i];
    easyUserTitleHeaders[headerI] = titleI;
  }
  
  var newData = [easyUserTitleHeaders];
  newData.push.apply(newData, data);
  
  return newData;
}

function saveToFile(csvData, pathData, options)
{
  csv()
  .from.array(csvData.data)
  .to.path(pathData.destination, options);
}

function generatePlaceHolderFiles(data, pathData)
{
  var dir = pathData.placeHolderDir;
  data.forEach(function(d,i)
    {
      var id = d['cm:name'];
      var yearDir = d['fashion1:Anno'];
      yearDir = S(yearDir).replaceAll("'","").replaceAll(" ","_").s;
      
      var tmp = dir + PATH.sep + yearDir;
      if(!fs.existsSync(tmp))
      {
        fs.mkdirSync(tmp);
      }
      
      var dirPath = dir + PATH.sep + yearDir + PATH.sep + id;
      fs.mkdirSync(dirPath);
    });
}

function createMetadataFile(csvData, data, metaFilePath)
{
  var xmlVersion = '<?xml version="1.0" encoding="UTF-8"?>';
  var doctype = '<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">';
  
  var entry = '    <entry key="type">'+ csvData.type +'</entry>';
  var addedAspects = '    <entry key="aspects">cm:generalclassifiable,cm:templatable</entry>'; //, cm:templatable
  var cmTemplate = '    <entry key="cm:template">workspace://SpacesStore/98b97b62-64d1-4239-8d6e-e6c58e3235b4</entry>';
  var metadata = xmlVersion + '\n' + 
                   doctype + '\n' +
                   '  <properties>\n' + 
                   entry + '\n' +
                   addedAspects + '\n' +
                   cmTemplate;
  
  for(key in data)
  {
    if(data[key]==='N/A' &&
      (key==='fashion1:Lavorazione' ||
        key==='fashion1:Grafica' ||
        key==='fashion1:Colore' ||
        key==='fashion1:TipologiaModello'))
    {
      // NOP
    }
    else
    {
      entry = '    <entry key="' + key + '">' +
      data[key] +
      '</entry>';
      metadata += '\n' + entry;
    }
  }
  
  metadata += '\n  </properties>';
  
  //var metadataString = json2xml(metadata, { attributes_key: '$' });
  //console.log("Metadata:");
  //console.log(metadata);
  fs.writeFileSync(metaFilePath, metadata);
}

function generateMetadataFile(csvData, pathData)
{
  var data = csvData.data;
  var dir = pathData.placeHolderDir;
  data.forEach(function(d,i)
    {
      var id = d['cm:name'];
      var yearDir = d['fashion1:Anno'];
      yearDir = S(yearDir).replaceAll("'","").replaceAll(" ","_").s;
      
      var metaFilePath = dir + PATH.sep + yearDir + PATH.sep + id + '.metadata.properties.xml';
      createMetadataFile(csvData, d, metaFilePath);
    });
}

function getsubDirSrcPath(/*String*/ cmName, pathData)
{
  var path = cmName;
  path = S(path).left(3).s;
  
  var fileName = cmName + pathData.suffix;
  return {path:path, fileName:fileName};
}

function getSubDirDestPath(data, pathData)
{
  var id = data['cm:name'];
  var dir = pathData.placeHolderDir;
  var yearDir = data['fashion1:Anno'];
  yearDir = S(yearDir).replaceAll("'","").replaceAll(" ","_").s;
  
  yearDir = dir + PATH.sep + yearDir;
  
  if(!fs.existsSync(yearDir))
  {
    fs.mkdirSync(yearDir);
  }
  
  var path = yearDir + PATH.sep + id;
  
  return path;
}

function copyFile(srcPath, destPath)
{
  //console.log("Copying from " + srcPath);
  //console.log("\tto " + destPath);
  //fs.createReadStream(srcPath)
  //  .pipe(fs.createWriteStream(destPath));
  
  srcPath = S(srcPath).replaceAll('\\','/').s;
  destPath = S(destPath).replaceAll('\\','/').s;
  console.log("echo 'Copying "+srcPath+" to /cygdrive/z/" +destPath+ "'");
  console.log("cp "+srcPath + " /cygdrive/z/" + destPath);
}

function copySourceFiles(data, pathData)
{
  if(pathData.pathSourceFiles)
  {
    var sourceDir = pathData.pathSourceFiles;
    data.forEach(function(d,i)
      {
        var subDirSrcPath = getsubDirSrcPath(d['cm:name'], pathData);
        //console.log("Copy from: " + sourceDir + PATH.sep + subDirSrcPath.path + PATH.sep + subDirSrcPath.fileName + pathData.fileExtension);
        
        var srcPath = sourceDir + PATH.sep + subDirSrcPath.path + PATH.sep + subDirSrcPath.fileName + pathData.fileExtension;
        var subDirDestPath = getSubDirDestPath(d, pathData);
        var destPath = subDirDestPath + PATH.sep + subDirSrcPath.fileName + pathData.fileExtension;
        //console.log("To: " + destPath);
        copyFile(srcPath, destPath);
      });
  }
  else
  {
    console.log("No path to source file defined.");
  }
}

function csvManipulation(csvData, pathData)
{
  var modelJson = readJson(pathData.model);
  var mappingJson = readJson(pathData.mapping);
  mappingJson = mappingJson[csvData.type];
  
  pathData.pathSourceFiles = mappingJson.pathSourceFiles;
  pathData.suffix = mappingJson.suffix;
  pathData.fileExtension = mappingJson.fileExtension;
  
  var typeJson = modelJson[type];
  var headers = getHeaders(typeJson);
  headers = addCsvHeaders(headers);
  //console.log("Headers:", headers);
  
  csvData.data.forEach(function(d,i)
    {
      fixValues(d, headers, typeJson);
    });
  
  //var data = buildData(csvData.data);
  deleteFolderRecursive(pathData.placeHolderDir);
  fs.mkdirSync(pathData.placeHolderDir);
  generatePlaceHolderFiles(csvData.data, pathData);
  generateMetadataFile(csvData, pathData);
  copySourceFiles(csvData.data, pathData);
  csvData.data = addEmptyRow(csvData.data, headers);
  
  var options =
  {
    delimiter: ";",
    header: true,
    quoted: true,
    columns: headers
  };
  
  //saveToFile(csvData, pathData, options);
  
  //console.log(csvData.data[0]);
}

// body

var type = process.argv[2];
var pathCsv = process.argv[3];
var pathModel = process.argv[4];
var pathMapping = process.argv[5];
var pathDestinationCsv = process.argv[6];
var pathSourceFile = process.argv[7];

if(!type ||
   !pathCsv ||
   !pathModel ||
   !pathMapping ||
   !pathDestinationCsv)
{
  console.log("Missing parameters");
  console.log("Usage:");
  console.log("node <js> typeName pathToCsv.csv pathToModel.json pathToMapping.json pathToDestinationCsv.csv");
}
else
{
  console.log("Type: ", type);
  console.log("Path pathCsv: ", pathCsv);
  console.log("Path pathModel: ", pathModel);
  console.log("Path pathMapping: ", pathMapping);
  console.log("Path pathDestinationCsv: ", pathDestinationCsv);
  
  var pathData =
  {
    csv: pathCsv,
    model: pathModel,
    mapping: pathMapping,
    destination: pathDestinationCsv,
    placeHolderDir: "placeHolders",
    placeHolderFile: "placeFile",
    placeHolderExt: "txt"
  };
  
  var csvData = 
  {
    type: type,
    data: []
  };
  
  csv().from.path(pathCsv, {delimiter:"\t", columns:true})
  .to.array(function(data)
    {
      //if(!csvData.headers && data.length>0)
      //{
      //  csvData.headers = [];
      //  for(key in data)
      //  {
      //    csvData.headers.push(key);
      //  }
      //}
      csvData.data = data;
      csvManipulation(csvData, pathData);
    });
}